﻿#define _CRT_SECURE_NO_WARNINGS
//【进阶】46.单例模式+类型转换
//【头文件包含】
//C++的主要头文件
#include<iostream>//c++的输入输出流
using namespace std;
#include<algorithm>
#include<string>
#include<vector>
#include<list>
//C的主要头文件
//#include<stdio.h>
#include<stdlib.h>
//#include<assert.h>
//#include<string.h> 
#include <thread>
#include <mutex>


//【命名空间】

//【类声明】
//设计一个只能在堆上创建对象的类
class HeapOnly
{
public:
	static HeapOnly* GetObj()
	{
		return new HeapOnly;
	}
private:
	//禁止公开构造
	HeapOnly() {}

	//禁止拷贝构造
	//HeapOnly(const HeapOnly&);
	// or
	HeapOnly(const HeapOnly&) = delete;
};


//设计一个只能在栈上的类
class StackOnly
{
public:
	static  StackOnly GetObj()
	{
		return  StackOnly();
	}
private:
	StackOnly() {};
	
};

//设计一个单例模式(懒汉模式)
namespace Lazy
{
	class Singleton
	{
	public:
		static Singleton* GetInstance()
		{
			//_mtx.lock();
			if (_pinst == nullptr)//双检查
			{
				unique_lock<mutex> lock(_mtx);
				if (_pinst == nullptr)
				{
					_pinst = new Singleton;
				}
			}
			//_mtx.unlock();

			return _pinst;
		}
		static void DelInstance()
		{
			unique_lock<mutex> lock(_mtx);
			delete _pinst;
			_pinst = nullptr;
		}
		Singleton(const Singleton& s) = delete;
	private:
		Singleton() {}
		// 防拷贝
		Singleton& operator=(Singleton const&);

		static Singleton* _pinst;
		static mutex _mtx;
	};
	class GC
	{
	public:
		~GC()
		{
			Singleton::DelInstance();
		}

	};
}

namespace Hungry
{
	class Singleton
	{
	public:
		static Singleton* GetInstance()
		{
			return &_inst;
		}
		Singleton(const Singleton& s) = delete;

	private:
		Singleton() {}

		static Singleton _inst;
	};

	Singleton Singleton::_inst;
}

Lazy::Singleton*Lazy::Singleton::_pinst = nullptr;
mutex Lazy::Singleton::_mtx;

static Lazy::GC gc;

class A
{
public:
	explicit A(int a=0)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& a)
	{
		cout << "A(const A& a)" << endl;
	}
	virtual void f() {}
private:
	int _a;
};
class B : public A
{
};

//【函数声明】
void Test1();void Test2();void Test3();void Test4();

//【主函数】
int main()
{
	cout << "****主函数开始****" << endl;
	Test1();
	Test2();
	Test3();
	Test4();
	
	cout << "****主函数结束****" << endl;
	return 0;
}

//【函数定义】

/*测试用例*/void Test1()
{
	cout << "****测试用例1开始****"<< endl;
	cout << Lazy::Singleton::GetInstance() << endl;
	cout << Lazy::Singleton::GetInstance() << endl;
	cout << Hungry::Singleton::GetInstance() << endl;
	cout << Hungry::Singleton::GetInstance() << endl;

	cout << "****测试用例1结束****" << endl << endl;
}

/*测试用例*/void Test2()
{
	cout << "****测试用例2开始****" << endl;
	{
	int i = 1;
	// 隐式类型转换
	double d0 = i;
	printf("%d, %.2f\n", i, d0);
	int* p0 = &i;
	// 显示的强制类型转换
	int address = (int)p0;
	printf("%x, %d\n", p0, address);

	d0 = static_cast<double>(i);//对应C的隐式类型转换
	p0 = reinterpret_cast<int*>(i);//对应C的大部分强制类型转换
	cout << d0 << " " << p0 << endl;
	}
	const int a = 2;
	int* p = const_cast<int*>(&a);
	*p = 30;
	cout <<"*p=" << *p << endl;
	cout << " a=" << a << endl;//这里a值未改变，是因为编译器对const对象存取优化机制导致的，编译器认为const对象为不变直接去寄存器更高效
	volatile const int a0 = 2;//增加volatile修饰可以取消优化
	int* p0 = const_cast<int*>(&a0);
	*p0 = 30;
	cout << "*p0=" << *p0 << endl;
	cout << " a0=" << a0 << endl;
	cout << "****测试用例2结束****" << endl<<endl;
}
void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功，能成功则转换，不能则返回
	B* pb1 = static_cast<B*>(pa);
	B* pb2 = dynamic_cast<B*>(pa);

	cout << "pb1:" << pb1 << endl;
	cout << "pb2:" << pb2 << endl;
}
/*测试用例*/void Test3()
{
	cout << "****测试用例3开始****" << endl;
	A a;
	B b;
	fun(&a);
	fun(&b);

	A a1(1);
	// explicit禁止了以下行为
	// 隐式转换-> A tmp(1); A a2(tmp);
	//A a2 = 1;
	cout << "****测试用例3结束****" << endl << endl;
}
/*测试用例*/void Test4()
{
	cout << "****测试用例4开始****" << endl;

	cout << "****测试用例4结束****" << endl << endl;
}
//【笔记】

//【进阶】46.单例模式+类型转换
//特殊类的设计
	// 设计模式（Design Pattern）是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
	// 已经学习的设计模式包括迭代器模式（封装性）和适配器模式（复用性）
	// 其他设计模式包括：工厂模式、装饰器模式、观察者模式
	// 重点学习：单例模式：
		// 一个类只能创建一个对象，并提供一个访问它的全局访问点，该实例被所有程序模块共享。
		// 饿汉模式
		// 不管将来用不用，程序启动时就创建一个唯一的实例对象
		// 简单，但可能会导致进程启动慢，且如果有多个单例类对象实例启动顺序不确定。
		// 懒汉模式
		// 延迟加载，使用实例对象时再创建对象。
		// 复杂，但第一次使用实例对象时，创建对象。进程启动无负载。多个单例实例启动顺序自由控制。
		
//C++的类型转换
	//C语言
		// 支持相近类型的隐式类型转换和强制类型转换
	//C++
		// 兼容C语言的隐式和强制，同时进一步规范了类型转换
	//C++的四种类型转换
		// 1. static_cast：对应C的隐式类型转换
		// 
		// 2. reinterpret_cast：对应C的大部分强制类型转换
		// 
		// 3. const_cast：对应C语言强制类型转换中用于去除const属性的功能
		// 
		// 4. dynamic_cas：用于将一个父类对象指针/引用转换为子类对象的指针/引用
			// a. dynamic_cast只能用于含有虚函数的类 （继承中的多态）
			// b. dynamic_cast会先检查是否能转换成功，能成功（切片父转子）则转换，不能（原生父转子）则返回0
			// 而切片是子类可转换为父类，默认就支持
		// explicit关键字，用于阻止经过转换构造函数进行的隐式转换发生
	// RTTI：Run-time Type identification的简称，即：运行时类型识别。
		//C++通过以下方式来支持RTTI：
		// 1. typeid运算符
		// 2. dynamic_cast运算符
		// 3. decltype





		









